package com.local.hwcard;

import android.content.Context;
import android.graphics.*;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import java.util.ArrayList;
import java.util.Arrays;

public class HWCardView extends View {
    private static final String TAG = "HWCardView";
    private static final int CORNER_RADIUS = 10;
    private static final int CARD_ONE_LINE = 11;

    private int currentTurn = 0;
    private int lastRole = 0;
    private int lastCardValue = 0;
    private int lastCardCount = 0;
    private int currentPoint = 50;
    private int gameType = 6;
    private int stepCount = 0;
    private int[] localCards = null;
    private int[] selectCards = null;
    private int localRole = 0;
    private boolean enableStartNewGame = true;
    private boolean isRoomStart = false;
    private ArrayList joinMessage = new ArrayList();
    private int t1SumCount = 0;
    private int t2SumCount = 0;

    private Paint t1Paint;
    private Paint t2Paint;
    private Paint cardPaint;
    private Paint cardEdgePaint;
    private Paint buttonPaint;
    private Paint buttonDisablePaint;
    private Paint buttonEdgePaint;
    private Paint messagePaint;
    private Paint message2Paint;
    private Paint welcomePaint;
    private Bitmap blankDisk;
    private Bitmap disk2;
    private Bitmap disk4;
    private Bitmap disk6;
    private Bitmap disk8;
    private Bitmap welcome;
    private Paint mPaint;
    private Player[] players;

    private OnMoveListener moveListener;
    private Thread watchdogThread;
    private boolean isRunning = false;
    private int watchdogCount = 0;

    public void setOnMoveListener(OnMoveListener listener) {
        this.moveListener = listener;
    }

    public interface OnMoveListener {
        void onOutsizeFocus(int x);
        void onCardViewError(String message);
        void onSendMessage(String message);
        void onCardSound(int cardNum, int cardValue);
    }

    public HWCardView(Context context) {
        super(context);
        init();
    }

    public HWCardView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public boolean getIsRoomStart() {
        return isRoomStart;
    }

    public void resetGame(String[] array) {
        watchdogCount = 0;

        setLocalCards(array[1]); //cards
        currentTurn = Integer.parseInt(array[2]); //currentTurn
        stepCount  = Integer.parseInt(array[3]); //stepCount
        lastRole = Integer.parseInt(array[4]); //lastRole
        lastCardCount = Integer.parseInt(array[5]); //lastCardCount
        lastCardValue = Integer.parseInt(array[6]); //lastCardValue
        currentPoint = Integer.parseInt(array[7]); //currentPoint
        String[] playerAllInfors = array[8].split(";"); //deviceIds
        gameType = playerAllInfors.length;

        for (int i = 0; i < gameType; i++) {
            String[] playerInfo = playerAllInfors[i].split(",");
            players[i].deviceId = playerInfo[0];
            if (DeviceInfor.getLocalID().equals(players[i].deviceId)) {
                localRole = i + 1;
            }
            players[i].cardNum = Integer.parseInt(playerInfo[1]);
            players[i].point = Integer.parseInt(playerInfo[2]);
            players[i].giveup = Integer.parseInt(playerInfo[3]);
            players[i].gameResult = Integer.parseInt(playerInfo[4]);
        }
        isRoomStart = true;

        if (currentTurn > 10) {
            // 游戏已经结束
            enableStartNewGame = true;
            caculateSumCount();
        } else {
            // 游戏未结束
            t1SumCount = 0;
            t2SumCount = 0;
        }

        invalidate();
    }

    private void caculateSumCount() {
        int t1Sum = 0;
        int t2Sum = 0;
        int start = 0;
        for (int i = 0; i < gameType; i++) {
            start = (i + 1) % 2;
            int behind = 0;
            if (players[i].giveup != 1) {
                for (int j = start; j < gameType; j+=2) {
                    if (players[j].giveup == 1) {
                        behind = 1;
                        break;
                    }

                    if (players[j].gameResult == 0 || players[j].gameResult > players[i].gameResult) {
                        behind = 1;
                        break;
                    }
                }
            }

            if (behind == 1) {
                if (i % 2 == 0) {
                    t2Sum += players[i].point;
                } else {
                    t1Sum += players[i].point;
                }
            } else {
                if (i % 2 == 0) {
                    t1Sum += players[i].point;
                } else {
                    t2Sum += players[i].point;
                }
            }
        }
        t1SumCount = t1Sum;
        t2SumCount = t2Sum;
    }

    private void updateStepCount(int receiveStepCount) {
        if (Math.abs(receiveStepCount - stepCount) > 1) {
            if (moveListener != null) {
                moveListener.onCardViewError("强制同步" + Math.abs(receiveStepCount - stepCount));
            }
        }
        stepCount = receiveStepCount;
    }

    public void ackPlay(String[] array) {
        int cardValue = -1;
        int cardCount = 0;

        int backupRole = lastRole;
        int backupCardCount = lastCardCount;
        int backupCardValue = lastCardValue;

        watchdogCount = 0;

        currentTurn = Integer.parseInt(array[1]); //currentTurn
        int receiveStepCount  = Integer.parseInt(array[2]); //stepCount
        lastRole = Integer.parseInt(array[3]); //lastRole
        cardCount = Integer.parseInt(array[4]); //lastCardCount
        cardValue = Integer.parseInt(array[5]); //lastCardValue
        int playRole = Integer.parseInt(array[6]); //playRole
        int playRemain = Integer.parseInt(array[7]); //playRemain
        currentPoint = Integer.parseInt(array[8]); //currentPoint

        // 有新玩家出牌
        if (backupRole != lastRole || backupCardCount != cardCount
                || backupCardValue != cardValue) {
            lastCardCount = cardCount;
            lastCardValue = cardValue;
            if (moveListener != null) {
                int soundValue;
                if (cardValue >= 53) {
                    soundValue = cardValue;
                } else {
                    if (cardValue == 11) {
                        soundValue = 13;
                    } else {
                        soundValue = (cardValue + 2) % 13;
                    }
                }
                moveListener.onCardSound(cardCount, soundValue);
            }
        }

        //更新玩家
        if (playRole == lastRole && playRole == localRole) {
            if (cardCount == selectCards.length) {
                selectCards = null;
                localCards = null;
            } else {
                int[] cardData = new int[selectCards.length - cardCount];
                int[] selectData = new int[selectCards.length - cardCount];
                int index = 0;
                for (int i = 0; i < selectCards.length; i++) {
                    if (selectCards[i] == 0) {
                        selectData[index] = 0;
                        cardData[index] = localCards[i];
                        index++;
                    }
                }
                selectCards = selectData;
                localCards = cardData;
            }
        } else {
            players[playRole - 1].cardNum = playRemain;
        }
        updateStepCount(receiveStepCount);
        invalidate();
    }

    public void syncPlay(String[] array) {
        lastRole = 0;
        lastCardCount = 0;
        lastCardValue = 0;

        watchdogCount = 0;

        currentTurn = Integer.parseInt(array[1]); //currentTurn
        int receiveStepCount  = Integer.parseInt(array[2]); //stepCount
        String sumCounts = array[3]; //{t1_sum,t2_sum}
        String[] sumInfors = sumCounts.split(",");
        if (sumInfors.length == 2) {


            t1SumCount = Integer.parseInt(sumInfors[0]);
            t2SumCount = Integer.parseInt(sumInfors[1]);
            if (t1SumCount > 0 || t2SumCount > 0) {
                enableStartNewGame = true;
            }
        }
        String[] playerAllInfors = array[4].split(";"); //deviceIds
        gameType = playerAllInfors.length;
        for (int i = 0; i < gameType; i++) {
            String[] playerInfo = playerAllInfors[i].split(",");
            players[i].deviceId = playerInfo[0];
            if (DeviceInfor.getLocalID().equals(players[i].deviceId)) {
                localRole = i + 1;
            }
            players[i].cardNum = Integer.parseInt(playerInfo[1]);
            players[i].point = Integer.parseInt(playerInfo[2]);
            players[i].giveup = Integer.parseInt(playerInfo[3]);
            players[i].gameResult = Integer.parseInt(playerInfo[4]);
        }
        updateStepCount(receiveStepCount);
        invalidate();
    }

    public void giveupPlay(String[] array) {
        watchdogCount = 0;
        int roleIndex = Integer.parseInt(array[2]);
        if (roleIndex > 0 && roleIndex <= gameType) {
            players[roleIndex - 1].giveup = 1;
            invalidate();
        }
    }

    public void setWaitRoom(String infor, int player) {
        currentTurn = 0;
        lastRole = 0;
        lastCardValue = 0;
        lastCardCount = 0;
        currentPoint = 50;
        gameType = 6;
        stepCount = 0;
        localCards = null;
        selectCards = null;
        localRole = 0;
        isRoomStart = false;
        enableStartNewGame = true;
        addJoinMessage(infor, player);
    }

    public void addJoinMessage(String infor, int player) {
        watchdogCount = 0;
        if (!isRoomStart) {
            if (joinMessage.size() < 10) {
                joinMessage.add(infor);
            } else {
                joinMessage.remove(0);
                joinMessage.add(infor);
            }

            invalidate();
        }
    }

    public void setLocalCards(String message) {
        if (message.isEmpty()) {
            selectCards = null;
            localCards = null;
            return;
        }
        String[] array = message.split(",");
        int[] cardData = new int[array.length];
        int[] selectData = new int[array.length];
        for (int i = 0; i < array.length; i++) {
            selectData[i] = 0;
            int v = Integer.parseInt(array[i]);
            if (v == 53 || v == 54) {
                cardData[i] = v;
            } else {
                v = v % 13;
                if (v == 0) {
                    cardData[i] = 13;
                } else {
                    cardData[i] = v;
                }
            }
        }
        Arrays.sort(cardData);
        localCards = cardData;
        selectCards = selectData;

        enableStartNewGame = false;
    }


    private void init() {
        setFocusable(true);
        setFocusableInTouchMode(true);
        players = new Player[8];
        for (int i = 0; i < 8; i++) {
            players[i] = new Player();
            players[i].role = i + 1;
            players[i].gameResult = 0;
        }

        //桌面背景
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setFilterBitmap(true);
        disk2 = BitmapFactory.decodeResource(getResources(), R.drawable.p2);
        disk4 = BitmapFactory.decodeResource(getResources(), R.drawable.p4);
        disk6 = BitmapFactory.decodeResource(getResources(), R.drawable.p6);
        disk8 = BitmapFactory.decodeResource(getResources(), R.drawable.p8);
        welcome = BitmapFactory.decodeResource(getResources(), R.drawable.welcome);
        blankDisk = BitmapFactory.decodeResource(getResources(), R.drawable.blank6);

        // 初始化奇数画笔
        t1Paint = new Paint();
        t1Paint.setColor(Color.BLACK);
        t1Paint.setStrokeWidth(2);
        t1Paint.setStyle(Paint.Style.FILL);
        t1Paint.setTextSize(38);

        // 初始化偶数画笔
        t2Paint = new Paint();
        t2Paint.setColor(Color.rgb(0,75, 200));
        t2Paint.setStrokeWidth(2);
        t2Paint.setStyle(Paint.Style.FILL);
        t2Paint.setTextSize(38);

        // 牌的画笔
        cardPaint = new Paint();
        cardPaint.setAntiAlias(true); // 抗锯齿
        cardPaint.setStrokeWidth(2);
        cardPaint.setColor(Color.rgb(253,255,248));
        cardPaint.setStyle(Paint.Style.FILL);

        cardEdgePaint = new Paint();
        cardEdgePaint.setAntiAlias(true); // 抗锯齿
        cardEdgePaint.setStrokeWidth(2);
        cardEdgePaint.setStyle(Paint.Style.STROKE); // 无填充，仅描边
        cardEdgePaint.setColor(Color.BLACK); // 边框颜色
        cardEdgePaint.setTextSize(36);
        cardEdgePaint.setTextAlign(Paint.Align.LEFT);

        //消息画笔
        messagePaint = new Paint();
        messagePaint.setColor(Color.BLACK);
        messagePaint.setStrokeWidth(2);
        messagePaint.setStyle(Paint.Style.FILL);
        messagePaint.setTextSize(45);

        message2Paint = new Paint();
        message2Paint.setColor(Color.rgb(0,75, 200));
        message2Paint.setStrokeWidth(2);
        message2Paint.setStyle(Paint.Style.FILL);
        message2Paint.setTextSize(45);

        //按钮画笔
        buttonPaint = new Paint();
        buttonPaint.setAntiAlias(true); // 抗锯齿
        buttonPaint.setStrokeWidth(2);
        buttonPaint.setColor(Color.rgb(63,81,181));
        buttonPaint.setStyle(Paint.Style.FILL);

        buttonDisablePaint = new Paint();
        buttonDisablePaint.setAntiAlias(true); // 抗锯齿
        buttonDisablePaint.setStrokeWidth(2);
        buttonDisablePaint.setColor(Color.rgb(203,203,203));
        buttonDisablePaint.setStyle(Paint.Style.FILL);

        buttonEdgePaint = new Paint();
        buttonEdgePaint.setAntiAlias(true); // 抗锯齿
        buttonEdgePaint.setStrokeWidth(2);
        buttonEdgePaint.setStyle(Paint.Style.FILL); // 无填充，仅描边
        buttonEdgePaint.setColor(Color.WHITE); // 边框颜色
        buttonEdgePaint.setTextSize(40);
        buttonEdgePaint.setTextAlign(Paint.Align.LEFT);

        welcomePaint = new Paint();
        welcomePaint.setAntiAlias(true);
        welcomePaint.setStyle(Paint.Style.STROKE);
        welcomePaint.setStrokeWidth(20);
        welcomePaint.setColor(Color.rgb(46,61,80));

        isRunning = true;

        watchdogThread = new Thread(() -> {
            while (isRunning && !Thread.currentThread().isInterrupted()) {
                try {
                    Thread.sleep(1000);
                    watchdogCount++;
                    if (watchdogCount > 45) {
                        Log.e(TAG, "watchdog reload");
                        watchdogCount = 0;
                        if (moveListener != null) {
                            moveListener.onSendMessage("RELOAD:" + DeviceInfor.getLocalID());
                        }
                    }
                } catch (Exception e) {
                    Log.e(TAG, "watchdog error: " + e.getMessage());
                }
            }

        });
        watchdogThread.start();
    }

    public void onDestroy() {
        try {
            isRunning = false;
            if (watchdogThread != null) {
                watchdogThread.interrupt();
                watchdogThread = null;
            }
        } catch (Exception e) {
            Log.e(TAG, "watchdog error: " + e.getMessage());
        }
    }

    public int getCurrentTurn() {
        return currentTurn;
    }

    void sendStartGame(int i) {
        if (moveListener != null) {
            moveListener.onSendMessage("START:" + i + ":" + DeviceInfor.getLocalID());
        }
        if (moveListener != null) {
            moveListener.onCardViewError("开始" + i + "人游戏");
        }
    }

    void skipCard() {
        if (moveListener != null) {
            moveListener.onSendMessage("SKIP:" + DeviceInfor.getLocalID());
        }
    }

    void sendCard() {
        if (localRole != currentTurn) {
            return;
        }
        
        int cardCount = 0;
        int cardValue = -1;
        for (int i = 0; i < selectCards.length; i++) {
            if (selectCards[i] == 1) {
                cardCount++;
                if (cardValue == -1) {
                    cardValue = localCards[i];
                } else if (cardValue != localCards[i]) {
                    if (moveListener != null) {
                        moveListener.onCardViewError("出的牌点数需要一样");
                    }
                    return;
                }
            }
        }

        if (lastRole != 0) {
            // 3张牌以内
            if (lastCardCount <= 3 && cardCount <= 3 &&
                    ((lastCardCount != cardCount) || (lastCardValue >= cardValue))) {
                if (moveListener != null) {
                    moveListener.onCardViewError("出的牌需要比桌上大");
                }
                return;
            }
            if (lastCardCount > 3 &&
                    ((lastCardCount > cardCount) ||
                            (lastCardCount == cardCount && lastCardValue >= cardValue))) {
                if (moveListener != null) {
                    moveListener.onCardViewError("出的牌需要比桌上大");
                }
                return;
            }
        }
        
        if (moveListener != null) {
            moveListener.onSendMessage(
                    String.format("CARD:%d:%d:%s", cardCount, cardValue,
                            DeviceInfor.getLocalID()));
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int viewWidth = this.getMeasuredWidth();
        int viewHeight = this.getMeasuredHeight();

        if (isRoomStart) {
            drawBoard(canvas, viewWidth, viewHeight);
            drawLocalPlayer(canvas, viewWidth, viewHeight);
        } else {
            drawJoinMessage(canvas, viewWidth, viewHeight);
        }

        drawGameButton(canvas, viewWidth, viewHeight);
    }

    void drawJoinMessage(Canvas canvas, int viewWidth, int viewHeight) {
        Rect dstRect = new Rect(0, 0, viewWidth, viewHeight / 4);
        canvas.drawBitmap(welcome, null, dstRect, welcomePaint);

        RectF mRectF = new RectF(150, viewHeight / 4,
                viewWidth - 150, viewHeight * 4 / 5);
        canvas.drawRoundRect(mRectF, 50, 50, welcomePaint);

        String room = DeviceInfor.getRoom();
        if (room == null || room.isEmpty()) {
            room = "公共";
        }
        canvas.drawText("房间名:" + room, 200, viewHeight / 4 + 100, messagePaint);
        canvas.drawText("玩家:" + DeviceInfor.getDisplayName(DeviceInfor.getLocalID()),
                viewWidth - 500, viewHeight / 4 + 100, messagePaint);
        canvas.drawLine(200, viewHeight / 4 + 150,
                viewWidth - 200, viewHeight / 4 + 150, messagePaint);
        int messageStartY = viewHeight / 4 + 220;
        for(int i = 0; i < joinMessage.size(); i++) {
            canvas.drawText(joinMessage.get(i).toString(),
                    200, messageStartY + i * 70, messagePaint);
        }
    }

    void drawBoard(Canvas canvas, int viewWidth, int viewHeight) {
        int width = viewWidth - 200;
        int height = (viewHeight - 200)/2;

        Rect dstRect = new Rect(100, 100, viewWidth - 100, viewHeight / 2 - 100);

        if (currentTurn > 10) {
            Paint paint = new Paint();
            paint.setColor(Color.rgb(62, 16,0));
            paint.setStrokeWidth(5);
            paint.setStyle(Paint.Style.FILL);
            paint.setTextSize(60);
            canvas.drawBitmap(blankDisk, null, dstRect, mPaint);

            canvas.drawText("黑方 " + t2SumCount + " 分",
                    (float) width / 2 - 70, (float) height / 3, paint);
            canvas.drawText("蓝方 " + t1SumCount + " 分",
                    (float) width / 2 - 70, (float) height / 3 + 100, paint);
            canvas.drawText(getGameResult(),
                    (float) width / 2 - 70, (float) height / 3 + 200, paint);
        } else {
            if (gameType == 2) {
                canvas.drawBitmap(disk2, null, dstRect, mPaint);
            } else if (gameType == 4) {
                canvas.drawBitmap(disk4, null, dstRect, mPaint);
            } else if (gameType == 6) {
                canvas.drawBitmap(disk6, null, dstRect, mPaint);
            } else if (gameType == 8){
                canvas.drawBitmap(disk8, null, dstRect, mPaint);
            }
            if (lastCardCount > 0) {
                canvas.drawText("场上有" + currentPoint + "分",
                        (float) width / 2 - 20, (float) height / 3, t1Paint);
                canvas.drawText(getLastCardInfo(),
                        (float) width / 2, (float) height / 3 + 100, t1Paint);

                drawCurrentCards(canvas,
                        (int) width / 2 - 120,
                        (int) height / 2 - 20,
                        lastCardCount, lastCardValue);
            }
        }

        if (gameType == 2) {
            draw2player(canvas, dstRect, viewWidth, viewHeight);
        } else if (gameType == 4) {
            draw4player(canvas, dstRect, viewWidth, viewHeight);
        } else if (gameType == 6) {
            draw6player(canvas, dstRect, viewWidth, viewHeight);
        } else if (gameType == 8){
            draw8player(canvas, dstRect, viewWidth, viewHeight);
        }
    }

    String getGameResult() {
        if (currentTurn / 10 == 1) {
            return "蓝方胜利";
        }
        else if (currentTurn / 10 == 2) {
            return "黑方胜利";
        }
        else {
            return "平 局";
        }
    }

    void drawLeftPlayer(Canvas canvas, int place, int index, int width, int height, Paint paint) {
        canvas.drawText(getIndexInfo(index),
                10, (float) place * height / 5 - 40, paint);
        canvas.drawText(DeviceInfor.getDisplayName(players[index].deviceId),
                10, (float) place * height / 5, paint);
        canvas.drawText(getPlayerCardInfor(index),
                10, (float) place * height / 5 + 40, paint);
        canvas.drawText(getTurnInfor(players[index].role),
                10, (float) place * height / 5 + 90, paint);
    }

    void drawRightPlayer(Canvas canvas, int place, int index, int width, int height, Paint paint) {
        canvas.drawText(getIndexInfo(index),
                width, (float) place * height / 5 - 40, paint);
        canvas.drawText(DeviceInfor.getDisplayName(players[index].deviceId),
                width, (float) place * height / 5, paint);
        canvas.drawText(getPlayerCardInfor(index),
                width, (float) place * height / 5 + 40, paint);
        canvas.drawText(getTurnInfor(players[index].role),
                width, (float) place * height / 5 + 90, paint);
    }

    void drawBottomPlayer(Canvas canvas, int index, int width, int height, Paint paint) {
        String indexString = getIndexInfo(index);
        if (indexString.length() == 1) {
            canvas.drawText(getIndexInfo(index),
                    (float) width / 2 - 50, height + 60, paint);
        } else {
            canvas.drawText(getIndexInfo(index),
                    (float) width / 2 - 100, height + 60, paint);
        }
        canvas.drawText(DeviceInfor.getDisplayName(players[index].deviceId),
                (float) width / 2, height + 40, paint);
        canvas.drawText(getPlayerCardInfor(index),
                (float) width / 2, height + 80, paint);
        canvas.drawText(getTurnInfor(players[index].role),
                (float) width / 2 + 200, height + 60, paint);
    }

    void drawTopPlayer(Canvas canvas, int index, int width, int height, Paint paint) {
        String indexString = getIndexInfo(index);
        if (indexString.length() == 1) {
            canvas.drawText(getIndexInfo(index),
                    (float) width / 2 - 50, 60, paint);
        } else {
            canvas.drawText(getIndexInfo(index),
                    (float) width / 2 - 100, 60, paint);
        }

        canvas.drawText(DeviceInfor.getDisplayName(players[index].deviceId),
                (float) width / 2, 40, paint);
        canvas.drawText(getPlayerCardInfor(index),
                (float) width / 2, 80, paint);
        canvas.drawText(getTurnInfor(players[index].role),
                (float) width / 2 + 200, 60, paint);
    }

    void draw2player(Canvas canvas, Rect dstRect, int viewWidth, int viewHeight) {
        int width = viewWidth - 180;
        int height = (viewHeight - 200)/2;

        drawLeftPlayer(canvas, 2, 0, width, height, t1Paint);

        drawRightPlayer(canvas, 2, 1, width, height, t2Paint);
    }

    void draw4player(Canvas canvas, Rect dstRect, int viewWidth, int viewHeight) {
        int width = viewWidth - 180;
        int height = (viewHeight - 200)/2;

        drawLeftPlayer(canvas, 1, 0, width, height, t1Paint);
        drawLeftPlayer(canvas, 2, 1, width, height, t2Paint);

        drawRightPlayer(canvas, 2, 2, width, height, t1Paint);
        drawRightPlayer(canvas, 1, 3, width, height, t2Paint);
    }

    void draw6player(Canvas canvas, Rect dstRect, int viewWidth, int viewHeight) {
        int width = viewWidth - 180;
        int height = (viewHeight - 200)/2;

        drawLeftPlayer(canvas, 1, 0, width, height, t1Paint);
        drawLeftPlayer(canvas, 2, 1, width, height, t2Paint);
        drawLeftPlayer(canvas, 3, 2, width, height, t1Paint);

        drawRightPlayer(canvas, 3, 3, width, height, t2Paint);
        drawRightPlayer(canvas, 2, 4, width, height, t1Paint);
        drawRightPlayer(canvas, 1, 5, width, height, t2Paint);
    }

    void draw8player(Canvas canvas, Rect dstRect, int viewWidth, int viewHeight) {
        int width = viewWidth - 180;
        int height = (viewHeight - 200)/2;

        drawLeftPlayer(canvas, 1, 0, width, height, t1Paint);
        drawLeftPlayer(canvas, 2, 1, width, height, t2Paint);
        drawLeftPlayer(canvas, 3, 2, width, height, t1Paint);

        drawBottomPlayer(canvas, 3, width, height, t2Paint);

        drawRightPlayer(canvas, 3, 4, width, height, t1Paint);
        drawRightPlayer(canvas, 2, 5, width, height, t2Paint);
        drawRightPlayer(canvas, 1, 6, width, height, t1Paint);

        drawTopPlayer(canvas, 7, width, height, t2Paint);

    }

    String getIndexInfo(int index) {
        String prefix = "  ";
        if (gameType == 8 && (index == 3 || index == 7)) {
            prefix = "";
        }
        if (players[index].giveup == 1) {
            return prefix + getRole(index + 1) + " \uD83C\uDFF3\uFE0F";
        } else if (players[index].cardNum == 0) {
            return prefix + getRole(index + 1) + " ✅";
        } else {
            return prefix + getRole(index + 1);
        }
    }

    String getTurnInfor(int role) {
        if (role == lastRole) {
            return "\uD83E\uDD47\uD83E\uDD47";
        }
        else if (role == currentTurn) {
            return "\uD83D\uDD25";
        }
        return "";
    }

    String getPlayerCardInfor(int index) {
        if (players[index].giveup == 1) {
            return String.format("%d分 投降", players[index].point);
        } else if (players[index].cardNum == 0) {
            if (players[index].gameResult == 0) {
                return String.format("%d分", players[index].point);
            } else {
                return String.format("%d分 第%d", players[index].point, players[index].gameResult);
            }
        } else if (players[index].cardNum < 10) {
            return String.format("%d分 剩%d", players[index].point, players[index].cardNum);
        } else {
            return String.format("%d分", players[index].point);
        }
    }

    String getLastCardInfo() {
        String cardDisplay;
        if (lastCardValue == 53) {
            cardDisplay = "小王";
        } else if (lastCardValue == 54) {
            cardDisplay = "大王";
        } else {
            cardDisplay = getValueText(lastCardValue);
        }
        return lastCardCount + "张" + cardDisplay;
    }

    void drawLocalPlayer(Canvas canvas, int viewWidth, int viewHeight) {
        int baseX = getCardStartX(viewWidth);
        int baseY = getCardStartY(viewHeight);
        int cellW = getCardCellW(viewWidth);
        int cellH = getCardCellH(viewHeight);

        String side = "黑方";
        Paint paint = messagePaint;
        if (localRole % 2 == 0) {
            paint = message2Paint;
            side = "蓝方";
        }
        canvas.drawText(DeviceInfor.getDisplayName(DeviceInfor.getLocalID())
                        + getRole(localRole) + " " + side,
                baseX, (float) viewHeight / 2 + 50, paint);
        if (currentTurn < 10) {
            canvas.drawText(getLocalPlayInfo(),
                    baseX + 320, (float) viewHeight / 2 + 50, paint);
            canvas.drawText(getAdvisorInfo(), baseX, (float) viewHeight / 2 + 120, paint);

            if (selectCards != null) {
                int cardCount = 0;
                for (int i = 0; i < selectCards.length; i++) {
                    if (selectCards[i] == 1) {
                        cardCount++;
                    }
                }
                if (cardCount > 0) {
                    canvas.drawText("已选" + cardCount + "张牌",
                            baseX + 850, (float) viewHeight / 2 + 50, paint);
                }
            }
        }

         // 画当前玩家的牌
        if (localCards != null) {
            for (int j = 0; j < 4; j++) {
                for (int i = 0; i < CARD_ONE_LINE && i + j * CARD_ONE_LINE < localCards.length; i++) {
                    if (selectCards[i + j * CARD_ONE_LINE] == 0) {
                        drawCard(canvas,
                                baseX + i * cellW,
                                baseY + j * cellH,
                                localCards[i + j * CARD_ONE_LINE]);
                    } else {
                        drawCard(canvas,
                                baseX + i * cellW,
                                baseY + j * cellH - 30,
                                localCards[i + j * CARD_ONE_LINE]);
                    }

                }
            }
        }
    }

    void drawGameButton(Canvas canvas, int viewWidth, int viewHeight) {
        float buttonX = getButtonX(viewWidth);
        float buttonY = getButtonY(viewHeight);
        RectF rect;

        // 游戏结束或游戏未开始
        if (currentTurn > 10 || !isRoomStart) {
            if (enableStartNewGame) {
                rect = new RectF(buttonX, buttonY -10, buttonX + 300, buttonY + 90);
                canvas.drawRoundRect(rect,
                        4 * CORNER_RADIUS, 4 * CORNER_RADIUS, buttonPaint);
                canvas.drawText("开始6人局", buttonX + 60, buttonY + 50, buttonEdgePaint);


                rect = new RectF(buttonX + 500, buttonY - 10, buttonX + 800, buttonY + 90);
                canvas.drawRoundRect(rect,
                        4 * CORNER_RADIUS, 4 * CORNER_RADIUS, buttonPaint);
                canvas.drawText("开始8人局", buttonX + 560, buttonY + 50, buttonEdgePaint);


                rect = new RectF(buttonX, buttonY + 100, buttonX + 300, buttonY + 200);
                canvas.drawRoundRect(rect,
                        4 * CORNER_RADIUS, 4 * CORNER_RADIUS, buttonPaint);
                canvas.drawText("开始2人局", buttonX + 60, buttonY + 160, buttonEdgePaint);


                rect = new RectF(buttonX + 500, buttonY + 100, buttonX + 800, buttonY + 200);
                canvas.drawRoundRect(rect,
                        4 * CORNER_RADIUS, 4 * CORNER_RADIUS, buttonPaint);
                canvas.drawText("开始4人局", buttonX + 560, buttonY + 160, buttonEdgePaint);
            }

        }

        // 在打牌过程中
        if (currentTurn < 10 && currentTurn != 0 && isRoomStart) {
            rect = new RectF(buttonX, buttonY, buttonX + 300, buttonY + 100);
            if (localRole == currentTurn) {
                canvas.drawRoundRect(rect,
                        4 * CORNER_RADIUS, 4 * CORNER_RADIUS, buttonPaint);
            } else {
                canvas.drawRoundRect(rect,
                        4 * CORNER_RADIUS, 4 * CORNER_RADIUS, buttonDisablePaint);
            }
            canvas.drawText("出 牌", buttonX + 100, buttonY + 60, buttonEdgePaint);

            rect = new RectF(buttonX + 500, buttonY, buttonX + 800, buttonY + 100);
            if (localRole == currentTurn && lastCardCount != 0) {
                canvas.drawRoundRect(rect,
                        4 * CORNER_RADIUS, 4 * CORNER_RADIUS, buttonPaint);
            } else {
                canvas.drawRoundRect(rect,
                        4 * CORNER_RADIUS, 4 * CORNER_RADIUS, buttonDisablePaint);
            }
            canvas.drawText("跳 过", buttonX + 600, buttonY + 60, buttonEdgePaint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int viewWidth = this.getMeasuredWidth();
        int viewHeight = this.getMeasuredHeight();
        float buttonX = getButtonX(viewWidth);
        float buttonY = getButtonY(viewHeight);

        if (currentTurn > 10 || !isRoomStart) {
            // 出完牌了
            if (enableStartNewGame) {
                if (event.getX() > buttonX && event.getX() < buttonX + 300 &&
                        event.getY() > buttonY - 10 && event.getY() < buttonY + 90) {
                    sendStartGame(6);
                }

                if (event.getX() > buttonX + 500 && event.getX() < buttonX + 800 &&
                        event.getY() > buttonY - 10 && event.getY() < buttonY + 90) {
                    sendStartGame(8);
                }

                if (event.getX() > buttonX && event.getX() < buttonX + 300 &&
                        event.getY() > buttonY + 100 && event.getY() < buttonY + 200) {
                    sendStartGame(2);
                }

                if (event.getX() > buttonX + 500 && event.getX() < buttonX + 800 &&
                        event.getY() > buttonY + 100 && event.getY() < buttonY + 200) {
                    sendStartGame(4);
                }
            }
        }

        if (currentTurn < 10 && currentTurn != 0 && isRoomStart) {
            if (localRole == currentTurn) {
                if (event.getX() > buttonX && event.getX() < buttonX + 300 &&
                        event.getY() > buttonY && event.getY() < buttonY + 100) {
                    sendCard();
                }
                if (lastCardCount != 0) {
                    if (event.getX() > buttonX + 500 && event.getX() < buttonX + 800 &&
                            event.getY() > buttonY && event.getY() < buttonY + 100) {
                        skipCard();
                    }
                }

            }

            // 选择牌
            int baseX = getCardStartX(viewWidth);
            int baseY = getCardStartY(viewHeight);
            int cellW = getCardCellW(viewWidth);
            int cellH = getCardCellH(viewHeight);

            int i = (int) (event.getX() - baseX) / cellW;
            int j = (int) (event.getY() - baseY) / cellH;
            if (i >= 0 && i <= 10) {
                int index = i + j * CARD_ONE_LINE;
                if (index >= 0 && index < localCards.length) {
                    if (selectCards[index] == 0) {
                        selectCards[index] = 1;
                    } else {
                        selectCards[index] = 0;
                    }
                    invalidate();
                }
            }
        }

        return super.onTouchEvent(event);
    }

    int getCardStartX(int viewWidth) {
        int baseX = (viewWidth - 100 * CARD_ONE_LINE) / 2;
        if (baseX < 30) {
            baseX = 30;
        }
        return baseX;
    }

    int getCardStartY(int viewHeight) {
        return viewHeight / 2 + 200;
    }

    int getCardCellW(int viewWidth) {
        int cellw = (viewWidth - 120) / 11;
        if (cellw > 100) {
            cellw = 100;
        }
        return cellw;
    }
    int getCardCellH(int viewHeight) {
        return (viewHeight / 2 - 400) / 4;
    }

    float getButtonX(int viewWidth) {
        return (float)(viewWidth - 200) / 2 - 300;
    }

    float getButtonY(int viewHeight) {
        return (float)(viewHeight - 200);
    }

    String getLocalPlayInfo() {
        if (localRole > 0 && localRole < 9) {
            if (localCards == null) {
                return "已有" + players[localRole - 1].point + "分  已出完";
            } else {
                return "已有" + players[localRole - 1].point + "分  剩" + localCards.length + "张";
            }
        }
        return "";
    }

    String getAdvisorInfo() {
        String message = "";
        if (lastRole != 0) {
            String lastPlayer = "对方";
            if (lastRole % 2 == localRole % 2) {
                lastPlayer = "同伴";
            }
            message += ("当前" + lastPlayer + "大");
        }
        if (currentTurn > 0) {
            if (!message.isEmpty()) {
                message += "，";
            }
            if (localRole == currentTurn) {
                message += ("轮到自己出牌");
            } else {
                String side = "黑方";
                if (currentTurn % 2 == 0) {
                    side = "蓝方";
                }
                message += ("轮到" + getRole(currentTurn) + side + "出牌");
            }
        }
        return message;
    }

    String getRole(int role) {
        switch (role) {
            case 1:
                return "①";
            case 2:
                return "②";
            case 3:
                return "③";
            case 4:
                return "④";
            case 5:
                return "⑤";
            case 6:
                return "⑥";
            case 7:
                return "⑦";
            case 8:
                return "⑧";
        }
        return "";
    }

    public void drawCurrentCards(Canvas canvas, int x, int y, int cardNum, int cardValue) {
        int OFFSET_X = 28;

        // 绘制每张牌
        int currentX;
        RectF rect;
        for (int i = 0; i < cardNum; i++) {
            // 计算当前牌的位置（依次偏移）
            currentX = (int)(x + i * OFFSET_X + (13 - cardNum) * 12.5);

            drawCard(canvas, currentX, y, cardValue);
        }
    }

    void drawCard(Canvas canvas, int x, int y, int cardValue) {

        RectF rect = new RectF(x, y, x + 100, y + 150);

        // 实心牌
        canvas.drawRoundRect(rect, CORNER_RADIUS, CORNER_RADIUS, cardPaint);

        // 边框和数字
        canvas.drawRoundRect(rect, CORNER_RADIUS, CORNER_RADIUS, cardEdgePaint);
        canvas.drawText(getValueText(cardValue), x + 10, y + 35, cardEdgePaint);
    }

    private String getValueText(int value) {
        if (value < 9) {
            return String.valueOf(value + 2);
        }
        switch (value) {
            case 9: return "J";
            case 10: return "Q";
            case 11: return "K";
            case 12: return "A";
            case 13: return "2";
        }
        if (value == 53) {
            return "小";
        }
        if (value == 54) {
            return "王";
        }
        return "";
    }

}